﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
using System.Runtime.Serialization;

namespace VideoClipNameHelper
{
    //===========================================================================================================================
    [DataContract]
    [AttributeUsage(AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
    public class VideoFile:System.Attribute
    {
        //Maria Muldaur - Midnight at the Oasis (636x480+448AC3_6).avi
        //Maria Muldaur - Midnight at the Oasis [636x480+448AC3_6].avi - teraz
        /// <summary>
        /// with path
        /// </summary>
        [DataMember]
        public string PathName { get; set; }
        //public byte [] Checksum { get; private set; }
        [DataMember]
        public VideoClipData vcd { get; set; }
        //[DataMember]
        //public bool isOK { get; set; }
        //
        [DataMember]
        public long FileLength { get; set; }
        [DataMember]
        public DateTime ModificationDT { get; set; }
        //[DataMember]
        //public int VideoArea { get; set; }// Height*Width
        //[DataMember]
        //public int AudioBitRate { get; set; }
        //
        //
        /// <summary>
        /// with extension
        /// </summary>
        public string FileName()
        {
            return System.IO.Path.GetFileName(PathName);
        }
        public string FileNameWithoutExtension()
        {
            return System.IO.Path.GetFileNameWithoutExtension(PathName);
        }
        //
        //
        public VideoFile()
        {
            this.PathName = "";
            vcd = null;
            //
            this.FileLength = 0;
            //this.VideoArea = 0;
            //this.AudioBitRate = 0;
        }

        public VideoFile(string pathName, bool isOK, VideoClipData vcd)
        {
            this.PathName = System.IO.Path.GetFullPath(pathName);
            //this.Checksum = CalculateMD5Hash(this.FileName);
            this.ModificationDT = System.IO.File.GetLastWriteTime(pathName);
            this.FileLength = (new System.IO.FileInfo(pathName)).Length;
            this.vcd = vcd;
        }
        public VideoFile(VideoFile vf)
        {
            this.PathName = vf.PathName;
            //this.Checksum = new byte[vf.Checksum.Length];
            //Buffer.BlockCopy(vf.Checksum, 0, this.Checksum, 0, vf.Checksum.Length);
            vcd = new VideoClipData(vf.vcd);
            //
            this.FileLength = vf.FileLength;
            this.ModificationDT = vf.ModificationDT;
            //this.VideoArea = vf.VideoArea;
            //this.AudioBitRate = vf.AudioBitRate;
        }

        public override int GetHashCode()
        {
            return this.FileName().ToLowerInvariant().GetHashCode();
        }
        public static bool operator ==(VideoFile vf1, VideoFile vf2)
        {
            if (object.ReferenceEquals(null, vf1) && object.ReferenceEquals(null, vf2)) return true;
            if (object.ReferenceEquals(null, vf1) || object.ReferenceEquals(null, vf2)) return false;
            return (vf1.FileLength == vf2.FileLength) && (0 == string.Compare(vf1.FileName(), vf2.FileName(), true));
        }
        public static bool operator !=(VideoFile vf1, VideoFile vf2)
        {
            if (object.ReferenceEquals(null, vf1) && object.ReferenceEquals(null, vf2)) return false;
            if (object.ReferenceEquals(null, vf1) || object.ReferenceEquals(null, vf2)) return true;
            return (vf1.FileLength != vf2.FileLength) || (0 != string.Compare(vf1.FileName(), vf2.FileName(), true));
        }

        public override bool Equals(Object obj)
        {
            VideoFile vf = obj as VideoFile;
            if (vf == null)
                return false;
            else
                return FileName().Equals(vf.FileName());
        }

        private byte[] CalculateMD5Hash(string input)
        {
            // step 1, calculate MD5 hash from input
            byte[] hash = null;
            using (System.Security.Cryptography.MD5 md5 = System.Security.Cryptography.MD5.Create())
            {
                hash = md5.ComputeHash(System.Text.Encoding.UTF8.GetBytes(input));
            }
            return hash;
            /*
            // step 2, convert byte array to hex string
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < hash.Length; i++)
            {
                sb.Append(hash[i].ToString("X2"));
            }
            return sb.ToString();
            */
        }
        //=========================================================================================================================================
        public static int LoadClipsFromDisk(string[] sourceDirectories, ref List<VideoFile> sourceVideoFiles, List<string> errList)
        {
            //
            int nErrors = 0;
            int filesCount = 0;
            foreach (string srcDir in sourceDirectories)
            {
                if (System.IO.Directory.Exists(srcDir))
                {
                    foreach (string f in System.IO.Directory.EnumerateFiles(srcDir, "*.mkv", System.IO.SearchOption.TopDirectoryOnly))
                    {
                        filesCount++;
                    }
                }
            }
            //
            sourceVideoFiles = new List<VideoFile>(filesCount + 100);// więcej na wszelki wypadek
                                                                     //
            foreach (string srcDir in sourceDirectories)
            {
                Console.WriteLine("[{0}]", srcDir);
                if (!System.IO.Directory.Exists(srcDir))
                {
                    Console.WriteLine("*****Cant find dir****");
                    errList.Add("Cant find dir: [" + srcDir + "]");
                    continue;
                }
                foreach (string f in System.IO.Directory.EnumerateFiles(srcDir, "*.mkv", System.IO.SearchOption.TopDirectoryOnly))
                {
                    VideoClipNameHelper.VideoClipData vc = new VideoClipNameHelper.VideoClipData();
                    string err;
                    if ("" == (err = VideoClipNameHelper.VideoClipData.Parse(System.IO.Path.GetFileNameWithoutExtension(f), vc)))
                    {
                        sourceVideoFiles.Add(new VideoFile(f, true, vc));
                    }
                    else
                    {
                        nErrors++;
                        Console.WriteLine("ERR:" + err + ":" + f);
                        errList.Add(err + ":" + f);
                    }

                }
            }
            Console.WriteLine(".");
            //
            return nErrors;
        }
        //===========================================================================================================================
    }//class
    //===========================================================================================================================
    //===========================================================================================================================
    //===========================================================================================================================
    /*
    public class vfComprer000 : IEqualityComparer<VideoFile>
    {
        private struct VF
        {
            public string Artist;
            public string Title;
            public int Length;
        }
        public int Compare(VideoFile vf1, VideoFile vf2)
        {
            //
            if (0 == string.Compare(vf1.vcd.Artist, vf2.vcd.Artist, true) && 0 == string.Compare(vf1.vcd.Title, vf2.vcd.Title, true))
            {
                int i1 = (int)(vf1.FileLength / 1000);
                int i2 = (int)(vf2.FileLength / 1000);
                //
                return i1 - i2;
            }
            return 1;
        }
        public bool Equals(VideoFile vf1, VideoFile vf2)
        {
            if (0 == string.Compare(vf1.vcd.Artist, vf2.vcd.Artist, true) && 0 == string.Compare(vf1.vcd.Title, vf2.vcd.Title, true))
            {
                int i1 = (int)(vf1.FileLength / 1000);
                int i2 = (int)(vf2.FileLength / 1000);
                //
                return i1 == i2;
            }
            return false;
        }

    public int GetHashCode(VideoFile vf)
        {
            VF vfc = new VF() { Artist = vf.vcd.Artist, Title = vf.vcd.Title, Length = (int)vf.FileLength / 1000 };
            return vfc.GetHashCode();
        }
    }
        */
    //===========================================================================================================================
    /*
    public class vfComprer : IEqualityComparer<VideoFile>
    {
        private struct VF
        {
            public string Artist;
            public string Title;
            public int Length;
        }

        public bool Equals(VideoFile vf1, VideoFile vf2)
        {
            if (
                (vf1.vcd.Artist.Length == vf2.vcd.Artist.Length)
                &&
                (vf1.vcd.Title.Length == vf2.vcd.Title.Length)
                &&
                (0 == string.Compare(vf1.vcd.Artist, vf2.vcd.Artist, true))
                &&
                (0 == string.Compare(vf1.vcd.Title, vf2.vcd.Title, true))
                )
            {
                return true;
            }
            return false;
        }

        public int GetHashCode(VideoFile vf)
        {
            VF vfc = new VF() { Artist = vf.vcd.Artist, Title = vf.vcd.Title, Length = 0 };
            return vfc.GetHashCode();
        }
    }
    */
    public class vfComprerFull : IEqualityComparer<VideoFile>
    {
        private struct VF
        {
            public string Artist;
            public string Title;
            public int Length;
        }
        /*
        public int Compare(VideoFile vf1, VideoFile vf2)
        {
            //
            if (
                (0 == string.Compare(vf1.vcd.Artist, vf2.vcd.Artist, true))
                &&
                (0 == string.Compare(vf1.vcd.Title, vf2.vcd.Title, true))
                &&
                (vf1.vcd.TitleExtras.Count() == vf2.vcd.TitleExtras.Count())
                )
            {
                return 0;
            }
            return 1;
        }
        */
        public bool Equals(VideoFile vf1, VideoFile vf2)
        {
            if (
                (vf1.vcd.Artist.Length == vf2.vcd.Artist.Length)
                &&
                (vf1.vcd.Title.Length == vf2.vcd.Title.Length)
                &&
                (vf1.vcd.TitleExtras.Count() == vf2.vcd.TitleExtras.Count())
                &&
                (0 == string.Compare(vf1.vcd.Artist, vf2.vcd.Artist, true))
                &&
                (0 == string.Compare(vf1.vcd.Title, vf2.vcd.Title, true))
                &&
                VideoClipData.IsTitleExtrasEqual(vf1.vcd, vf2.vcd)
                )
            {
                return true;
            }
            return false;
        }
        
        public int GetHashCode(VideoFile vf)
        {
            VF vfc = new VF() { Artist = vf.vcd.Artist, Title = vf.vcd.Title, Length = 0 };
            return vfc.GetHashCode();
        }
    }//class vfComprerFull

}//namespace
